#include "model/clases/Metodo.h"
#include <iostream>
#include <string.h>

Metodo::Metodo(
		std::string tipoDatoDevuelto,
		Visibilidad visibilidad,
		const std::string& nombre) {

	this->tipoDatoDevuelto = tipoDatoDevuelto;
	this->visibilidad = visibilidad;
	this->nombre = nombre;

}

Metodo::Metodo() {

	this->tipoDatoDevuelto = "void";
	this->nombre = "metodo";

}


Metodo::Metodo(const Metodo& metodo) {
    this->tipoDatoDevuelto = metodo.tipoDatoDevuelto;
    this->visibilidad = metodo.visibilidad;
    this->nombre = metodo.nombre;

    std::vector<Parametro*>::const_iterator it;

    for(it = metodo.parametros.begin();it != metodo.parametros.end();it++){
        parametros.push_back(new Parametro(*(*it)));
    }

}

Metodo::~Metodo(){
    std::vector<Parametro*>::iterator it;

    for(it = parametros.begin();it != parametros.end();it++){
        delete (*it);
    }
}

std::string Metodo::getNombre()const{
    return nombre;
}
std::string Metodo::getTipoDatoDevuelto()const{
    return tipoDatoDevuelto.size() ? tipoDatoDevuelto : "void";
}
std::vector<Parametro*> Metodo::getParametros()const{
    return parametros;
}
Visibilidad Metodo::getVisibilidad()const{
    return visibilidad;
}

void Metodo::setNombre(const std::string& valor){
    nombre = valor;
}
void Metodo::setTipo(const std::string& valor){
    tipoDatoDevuelto = valor;
}
void Metodo::setVisibilidad(Visibilidad valor){
    visibilidad = valor;
}

void Metodo::agregarParametro(Parametro *parametro) {
    parametros.push_back(parametro);
}

void Metodo::remplazarParametros(std::vector<Parametro*> parametrosNuevos){
    std::vector<Parametro*>::iterator it;

    for(it = parametros.begin();it != parametros.end();it++){
        delete (*it);
    }

    parametros.clear();
    parametros = parametrosNuevos;
}

void Metodo::serialize(XmlWriter & writer_rep, XmlWriter & writer_comp){

	/* Serializo mis parametros */
	xmlNode* comp_hijo = writer_comp.addCurrentNodeChild(NODE_METODO, "");
	writer_comp.addProperty(comp_hijo, TARGET_NAME, nombre.c_str());
	writer_comp.addProperty(comp_hijo, "methodName", nombre.c_str());
	writer_comp.addProperty(comp_hijo, "returns", tipoDatoDevuelto.c_str());
	writer_comp.addProperty(comp_hijo, "visibility", Utils::visibilidadToString(visibilidad).c_str());
	xmlNode* nodoClase = writer_comp.getCurrentNode();
	writer_comp.setCurrentNode(comp_hijo);
	for (std::vector<Parametro*>::iterator it = parametros.begin();
			it != parametros.end(); it++) {
		(*it)->serialize(writer_rep, writer_comp);
	}
	writer_comp.setCurrentNode(nodoClase);
}

void Metodo::deserialize(XmlReader & reader){

}

void Metodo::deserialize(XmlReader & reader, XmlReader & readerModel){

	std::string nombre = readerModel.getCurrentNodeProperty(TARGET_NAME);
	this->setName(nombre);

	std::string methodName = readerModel.getCurrentNodeProperty("methodName");
	this->setNombre(methodName);

	std::string visibilidadString = readerModel.getCurrentNodeProperty("visibility");
	this->setVisibilidad(Utils::visibilidadFromString(visibilidadString));

	std::string tipoDatoDevuelto = readerModel.getCurrentNodeProperty("returns");
	this->setTipo(tipoDatoDevuelto);
	xmlNode* nodoMetodo = readerModel.getCurrentNode();
	if (readerModel.hasChild()) {
		readerModel.setCurrentNode(readerModel.getCurrentNodeChild());
		while (readerModel.getCurrentNode()) {
			if (!strcmp(readerModel.getCurrentNodeName(), NODE_PARAM)) {
				Parametro* param = new Parametro();
				param->deserialize(reader,readerModel);
				this->agregarParametro(param);
			}
			if (readerModel.hastNextNode()) {
				readerModel.setCurrentNode(readerModel.nextNode());
			}
			else{
				readerModel.setCurrentNode(NULL);
			}
		}
	}
	readerModel.setCurrentNode(nodoMetodo);
}

std::string Metodo::description() {
	std::string d = "";
	d += Utils::visibilidadToString(this->visibilidad);
	d += " " + this->nombre;
	d += "(";
	for (unsigned int i = 0; i < parametros.size(); i++) {
		Parametro *p = parametros[i];
		d += p->description() + ", ";
	}
	d += ") : ";
	d += tipoDatoDevuelto.size() ? tipoDatoDevuelto : "void";
	return d;
}
